package dk.liljedahl.christian.apx.shipdaemon;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Timer;
import java.util.TimerTask;

import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.layout.RowData;
import org.eclipse.swt.layout.RowLayout;

import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.FileDialog;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Spinner;
import org.eclipse.swt.widgets.Text;
import org.jivesoftware.smack.XMPPConnection;
import org.jivesoftware.smack.packet.Message;

import cc.arduino.Arduino;
import dk.liljedahl.christian.apx.*;

import processing.serial.*;

import cc.arduino.*;
import dk.liljedahl.christian.apx.ArduinoFirmata;
import dk.liljedahl.christian.apx.DummyPApplet;
import dk.liljedahl.christian.apx.XMPPMachine;
import processing.core.PApplet;

/**
 * @author ChristianLiljedahl
 *
 */
public class ShipDaemonUI {
	static XMPPMachine xmppmachine; 
	static ArduinoFirmata arduino;
	static DummyPApplet dummyPApplet;
	
	static Mediator mediator;

	static XMPPConnection connection;
	
	static CheckArduinoParameters checkArduinoParameters;

	static Label statusLabel;
	static Text textUsername; 
	static Text textPassword;
	static Label arduinoDataLabel;
	static Text textScript; 
	static Text textResponseScript;
	static Text textDelay;
	static String filename = ""; // TODO - Default files could be nice
	static String filenameResponse = "";
	
	public static void main(String[] args) {
		final Display display = new Display ();
    	final Shell shell = new Shell(display);
    	    

    	// Some properties - Size and placement. To keep nicely sided next to the Processing window
    	shell.setSize(600,470);
    	//shell.setBounds(315, 0, 300, 300);
    	shell.setText("Ship Daemon");
    	//shell.setLayout(new FillLayout());
        shell.setLayout(new RowLayout());
        
        // turn on the enhanced debugger
        XMPPConnection.DEBUG_ENABLED = true;
    	mediator = new Mediator();

    	xmppmachine = new XMPPMachine(mediator);
    	dummyPApplet = new DummyPApplet();
    	
    	checkArduinoParameters = new CheckArduinoParameters(mediator);
    	
    	mediator.xmppmachine = xmppmachine;
    	mediator.responseScript = "";
    	mediator.eventScript = "";
    	
		final int periodArduinoCheck = 1000;  // repeat every sec.
		
		final Runnable timerArduino = new Runnable() {
		      public void run() {
		        	checkArduinoParameters.checkParameters(mediator.eventScript);
		        	int period = Integer.parseInt(textDelay.getText());
		        	display.timerExec(period, this);
		      }
		    };

    	// Add the widgets
		final Label labelU = new Label(shell, SWT.NORMAL);
		textUsername = new Text(shell, SWT.BORDER);
		final Label labelP = new Label(shell, SWT.NORMAL);
		textPassword = new Text(shell, SWT.BORDER);
		

		final Button button1 = new Button(shell, SWT.PUSH); // Open connection
		Button button9 = new Button(shell, SWT.PUSH); // See roster
        
		
		statusLabel = new Label(shell, SWT.NORMAL);
		Label sep1 = new Label(shell, SWT.SEPARATOR | SWT.HORIZONTAL);
		sep1.setLayoutData(new RowData(590, 4));
		
		Button button2 = new Button(shell, SWT.PUSH); // Get serial ports
	    final Combo combo = new Combo(shell, SWT.DROP_DOWN);

		Button button3 = new Button(shell, SWT.PUSH); // connetc to arduinoboard

		Button buttonArduinoDetails = new Button(shell, SWT.PUSH); // Arduino Details

		Button button4 = new Button(shell, SWT.PUSH); // Test analog 0
		arduinoDataLabel = new Label(shell, SWT.NORMAL);
		textScript = new Text(shell, SWT.MULTI | SWT.BORDER | SWT.WRAP | SWT.V_SCROLL);
		textScript.setLayoutData(new RowData(550, 200));
		//textScript.setText(GetScriptText(filename));
		Button button6 = new Button(shell, SWT.PUSH); // Load Script
		Button button7 = new Button(shell, SWT.PUSH); // Save Script
		Button button5 = new Button(shell, SWT.PUSH); // Start Checking
		final Label labelDelay = new Label(shell, SWT.NORMAL);
		textDelay = new Text(shell, SWT.BORDER);
		Button button8 = new Button(shell, SWT.PUSH); // Stop check
		final Label labelFilename = new Label(shell, SWT.NORMAL);
		labelFilename.setText(filename);
		labelFilename.setLayoutData(new RowData(300, 20));


		Label sep2 = new Label(shell, SWT.SEPARATOR | SWT.HORIZONTAL);
		sep2.setLayoutData(new RowData(590, 4));

		Button buttonSetPinmode = new Button(shell, SWT.PUSH); // Set pinmodes from pinmode script
		Button buttonResponseScript = new Button(shell, SWT.PUSH); // Response Script editor
	    labelU.setText("Username:");
		labelP.setText("Password:");
		
		
		// configure the widgets
		statusLabel.setSize(400,30);
		//statusLabel.setLocation(10, 100);
		statusLabel.setText("Not connected");
		
		
		button1.setText("Open connection");
		button1.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(SelectionEvent e) {
					xmppmachine.set_LocalUsername(textUsername.getText());
					xmppmachine.set_LocalPassword(textPassword.getText());

					statusLabel.setText("Opening connection");
	                connection = xmppmachine.openconnection();
	                if(connection != null && connection.isConnected()){
	                	statusLabel.setText("Connected");
	                }

			}
		});

		button2.setText("Get Serial Ports");
		button2.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(SelectionEvent e) {
				String ports[] = Arduino.list();
				for (String p: ports)
			    {
			      combo.add(p);
			    }

			}
		});

		button3.setText("Connect to Arduino");
		button3.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(SelectionEvent e) {
				// We should only allow this, if we have serial port selected
				try {
					arduino = new ArduinoFirmata(dummyPApplet, combo.getItem(combo.getSelectionIndex()), 57600);
			    	mediator.arduinoFirmata = arduino;
			    	
				} catch (Exception e1) {
					e1.printStackTrace();
				}

			}
		});

		button4.setText("Test analog 0");
		button4.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(SelectionEvent e) {
				// We should only allow this if Arduino is running
				if(mediator.arduinoFirmata != null){
					int analog0 = arduino.analogRead(0);
					arduinoDataLabel.setText("analog 0: " + analog0);
				}

			}
		});
		
		buttonArduinoDetails.setText("New scriptEditor");
		buttonArduinoDetails.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(SelectionEvent e) {
				
				
			}
		});

		arduinoDataLabel.setText("arduino data");
		

		buttonSetPinmode.setText("Set pinmodes");
		buttonSetPinmode.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(SelectionEvent e) {
				checkArduinoParameters.setPinModes(textScript.getText());
			}
		});

		button5.setText("Start Event Script");
		button5.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(SelectionEvent e) {
				// We should only allow this, if xmpp and Arduino are running
				if(mediator.arduinoFirmata != null && mediator.xmppmachine != null){
					// Update the mediator, we want to run the script in the window we se
					mediator.eventScript = textScript.getText();
					display.timerExec(periodArduinoCheck, timerArduino);
				}
			}
		});
		labelDelay.setText("Run every (ms):");
		textDelay.setText("1000");

		button8.setText("Stop Event Script");
		button8.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(SelectionEvent e) {
				display.timerExec(-1, timerArduino);

			}
		});
		
		button6.setText("Load Script");
		button6.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(SelectionEvent e) {
				
				// Display the open file dialog
				FileDialog dialog = new FileDialog(shell, SWT.OPEN);
			    filename = dialog.open();
			    labelFilename.setText(filename);
				textScript.setText(GetScriptText(filename));

			}
		});

		button7.setText("Save Script");
		button7.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(SelectionEvent e) {
				FileDialog dialog = new FileDialog(shell, SWT.SAVE);
				dialog.setFileName(filename);
			    filename = dialog.open();				
			    labelFilename.setText(filename);
				SetScriptText(textScript.getText(), filename);
			}
		});

		button9.setText("See friends");
		button9.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(SelectionEvent e) {
				String friends = xmppmachine.getAllFriendsS();
				final Shell dialog = new Shell(shell, SWT.APPLICATION_MODAL | SWT.DIALOG_TRIM);
				dialog.setSize(500, 400);
				dialog.setText("Friends");
		    	dialog.setLayout(new RowLayout());
		    	// Add Friend emailfield
				final Text textNewFriend = new Text(dialog, SWT.BORDER);
				textNewFriend.setLayoutData(new RowData(200, 20));

				// Add Friend button
				Button buttonAddFriend = new Button(dialog, SWT.PUSH); 
				buttonAddFriend.setText("Add");
				buttonAddFriend.addSelectionListener(new SelectionAdapter(){
					public void widgetSelected(SelectionEvent e){
						String FriendEmail = textNewFriend.getText();
						xmppmachine.SendFriendRequest(FriendEmail);
					}
				});


				// Friend List
		    	Text tRoster = new Text(dialog, SWT.MULTI | SWT.BORDER | SWT.WRAP | SWT.V_SCROLL | SWT.H_SCROLL);
				tRoster.setLayoutData(new RowData(450, 300));

				tRoster.setText(friends);
			    dialog.open();			    
			}
		});

		buttonResponseScript.setText("Edit response Script");
		buttonResponseScript.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(SelectionEvent e) {
				final Shell dialog = new Shell(shell, SWT.APPLICATION_MODAL | SWT.DIALOG_TRIM);
				dialog.setSize(600, 480);
				dialog.setText("Response Script");
		    	dialog.setLayout(new RowLayout());
				Button buttonLoad = new Button(dialog, SWT.PUSH); 
				Button buttonSave = new Button(dialog, SWT.PUSH); 
				final Label labelResponseFilename = new Label(dialog, SWT.NORMAL);
				Button buttonUseThisScript = new Button(dialog, SWT.PUSH); 
				labelResponseFilename.setText(filenameResponse);
				labelResponseFilename.setLayoutData(new RowData(300, 20));
				

		    	// Add Script field
				textResponseScript = new Text(dialog, SWT.MULTI | SWT.BORDER | SWT.WRAP | SWT.V_SCROLL);

				
				textResponseScript.setLayoutData(new RowData(550, 400));
				// Open if there is something to open
				if (!filenameResponse.equals("")){
					textResponseScript.setText(mediator.responseScript);
				}
		    	// Add Load and Save buttons
				buttonLoad.setText("Load");
				buttonLoad.addSelectionListener(new SelectionAdapter() {
					public void widgetSelected(SelectionEvent e) {
						
						// Display the open file dialog
						FileDialog dialog = new FileDialog(shell, SWT.OPEN);
					    filenameResponse = dialog.open();
					    labelResponseFilename.setText(filenameResponse);
					    textResponseScript.setText(GetScriptText(filenameResponse));

					}
				});

				buttonSave.setText("Save");
				buttonSave.addSelectionListener(new SelectionAdapter() {
					public void widgetSelected(SelectionEvent e) {
						FileDialog dialog = new FileDialog(shell, SWT.SAVE);
						dialog.setFileName(filenameResponse);
						filenameResponse = dialog.open();				
						labelResponseFilename.setText(filenameResponse); 
						SetScriptText(textResponseScript.getText(), filenameResponse);
					}
				});
		    	
				buttonUseThisScript.setText("Use this Script");
				buttonUseThisScript.addSelectionListener(new SelectionAdapter() {
					public void widgetSelected(SelectionEvent e) {
						mediator.responseScript = textResponseScript.getText();
					}
				});


			    dialog.open();			    
			}
		});
		
    	// Default Swt-stuff
		shell.open();
		while (!shell.isDisposed ()) {
			if (!display.readAndDispatch ()) display.sleep ();
		}
		// End the firmata serial-fuck - and kill the processing-dummy?
		if(arduino != null){
			arduino.dispose();
		}

		// End the xmpp connection
		if(connection != null && connection.isConnected()){connection.disconnect();} 
		display.dispose ();

	}
	
	private static String GetScriptText(String fileToLoad){
		// Load the Script from a file
		File file = new File(fileToLoad);
        StringBuffer contents = new StringBuffer();
        BufferedReader reader = null;

        try {
            reader = new BufferedReader(new FileReader(file));
            String text = null;

            // repeat until all lines is read
            while ((text = reader.readLine()) != null) {
                contents.append(text)
                    .append(System.getProperty(
                        "line.separator"));
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (reader != null) {
                    reader.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        
        // show file contents here

		return contents.toString();
		
	}


	private static void SetScriptText(String text, String fileToSave){
		try {
			BufferedWriter out = new BufferedWriter(new FileWriter(fileToSave));
			out.write(text);
			out.close();
		}
		catch (IOException e)
		{
			System.out.println("Exception ");		
		}
		
	}
	
}
